package com.yycx.module.file.provider.oss.client;


import cn.hutool.json.JSONUtil;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.*;
import com.yycx.common.base.entity.EntityMap;
import com.yycx.common.base.utils.FlymeUtils;
import com.yycx.common.constants.SettingConstant;
import com.yycx.common.utils.ApiAssert;
import com.yycx.common.utils.FileTypeUtils;
import com.yycx.common.utils.RedisUtils;
import com.yycx.module.file.client.entity.SysFile;
import com.yycx.module.file.client.vo.OssSetting;
import com.yycx.module.file.client.vo.SerializableStream;
import com.yycx.module.file.provider.enums.StoreTypeEnum;
import com.yycx.module.file.provider.oss.FileUploadUtil;
import com.yycx.module.file.provider.oss.common.MultipartUpload;
import com.yycx.module.file.provider.oss.listener.PutObjectProgressListener;
import com.yycx.module.file.provider.service.OssUploadService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FilenameUtils;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.List;

/**
 * 阿里云文件上传
 *
 * @author zyf
 */
@Component("ALI_OSS")
@Slf4j
public class AliOssClient implements OssUploadService {

    private RedisUtils redisUtils;

    private String bucketName;

    @Override
    public OssSetting getOssSetting() {
        String v = redisUtils.getConfig(StoreTypeEnum.ALI_OSS.name());
        if (FlymeUtils.isNotEmpty(v)) {
            return JSONUtil.toBean(v, OssSetting.class);
        }
        return null;
    }

    @Override
    public String getBaseOssPath() {
        OssSetting ossSetting = getOssSetting();
        String ossBasePath = ossSetting.getHttp() + ossSetting.getBucket() + "." + ossSetting.getEndpoint() + "/";
        return ossBasePath;
    }

    @Override
    public String getOssPath(String fileBasePath, String fileName) {
        //ossSmallPath = ossPath + "?x-oss-process=image/resize,m_fill,h_200,w_200";
        return getBaseOssPath() + fileBasePath + fileName;
    }

    @Override
    public String getLocalPath(String fileBasePath, String fileKey) {
        return getOssSetting().getFilePath() + "/" + fileBasePath+fileKey;
    }

    private OSS initOssClient() {
        OSS ossClient = null;
        OssSetting os = getOssSetting();
        if (FlymeUtils.isNotEmpty(os)) {
            String used = redisUtils.getConfig(SettingConstant.OSS_USED);
            if (used.equals(StoreTypeEnum.ALI_OSS.name())) {
                this.bucketName = os.getBucket();
                ossClient = new OSSClientBuilder().build(os.getHttp() + os.getEndpoint(), os.getAccessKey(), os.getSecretKey());
                // 如果该bucketName不存在，则创建
                if (!ossClient.doesBucketExist(bucketName)) {
                    ossClient.createBucket(bucketName);
                }
            }
        }
        return ossClient;
    }

    /**
     * 文件路径上传
     *
     * @param fileBasePath
     * @param filePath
     * @param fileKey
     * @return
     */
    @Override
    public String upload(String filePath, String fileName, SysFile sysFile, Long uid, String fileBasePath, String fileKey, Long userId, EntityMap params) {
        String objectID = fileBasePath + fileKey;
        OSS ossClient = initOssClient();
        if (FlymeUtils.isEmpty(ossClient)) {
            ApiAssert.failure("您还未配置阿里云OSS");
        }
        try {
            SerializableStream serializableStream = sysFile.getSerializableStream();
            File file = new File(filePath);
            InputStream inputStream = serializableStream.getInputStream();
            Long fileSize = file.length();
            PutObjectRequest putObjectRequest;
            if (FileUploadUtil.isPicture(FileUploadUtil.getExtend(fileKey))) {
                ObjectMetadata objectMetadata = new ObjectMetadata();
                objectMetadata.setContentType(FileTypeUtils.getMediaTypeValue(FilenameUtils.getExtension(objectID)));
                putObjectRequest = new PutObjectRequest(bucketName, objectID, inputStream, objectMetadata);
                putObjectRequest.withProgressListener(new PutObjectProgressListener());
                ossClient.putObject(putObjectRequest);
            } else {
                if (fileSize > MAX_PART_SIZE) {
                    MultipartUpload multipartUpload = new MultipartUpload(ossClient, objectID, bucketName);
                    multipartUpload.sliceUploadToAliyun(file, fileSize);
                } else {
                    ossClient.putObject(bucketName, objectID, inputStream);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (ossClient != null) {
                //ossClient.shutdown();
            }
        }

        return objectID;
    }

    /**
     * 文件流上传
     *
     * @param inputStream
     * @param key
     * @return
     */
    public String aliInputStreamUpload(InputStream inputStream, String key) {
        OSS ossClient = initOssClient();
        OssSetting os = getOssSetting();
        ossClient.putObject(bucketName, key, inputStream);
        ossClient.shutdown();
        return os.getHttp() + os.getBucket() + "." + os.getEndpoint() + SEPARATOR + key;
    }

    public String aliInputStream(FileInputStream inputStream, String key) {
        OssSetting os = getOssSetting();
        UploadFileRequest uploadFileRequest = new UploadFileRequest(bucketName, key);
        return null;
    }

    /**
     * 重命名
     *
     * @param fromKey
     * @param toKey
     */
    public String renameFile(String fromKey, String toKey) {

        OssSetting os = getOssSetting();
        copyFile(fromKey, toKey);
        deleteFile(fromKey);
        return os.getHttp() + os.getBucket() + "." + os.getEndpoint() + SEPARATOR + toKey;
    }

    /**
     * 复制文件
     *
     * @param fromKey
     */
    public String copyFile(String fromKey, String toKey) {
        OSS ossClient = initOssClient();
        if (FlymeUtils.isEmpty(ossClient)) {
            ApiAssert.failure("您还未配置阿里云OSS");
        }
        OssSetting os = getOssSetting();
        ossClient.copyObject(os.getBucket(), fromKey, os.getBucket(), toKey);
        ossClient.shutdown();
        return os.getHttp() + os.getBucket() + "." + os.getEndpoint() + SEPARATOR + toKey;
    }

    /**
     * 删除文件
     *
     * @param key
     */
    public void deleteFile(String key) {
        OSS ossClient = initOssClient();
        if (FlymeUtils.isEmpty(ossClient)) {
            ApiAssert.failure("您还未配置阿里云OSS");
        }
        OssSetting os = getOssSetting();
        // 创建OSSClient实例。
        ossClient.deleteObject(os.getBucket(), key);
        ossClient.shutdown();
    }

    /**
     * 批量删除
     *
     * @param objectIDList
     */
    public void deleteFile(List<String> objectIDList) {
        OSS ossClient = initOssClient();
        if (FlymeUtils.isEmpty(ossClient)) {
            ApiAssert.failure("您还未配置阿里云OSS");
        }
        // 删除文件。key等同于ObjectName，表示删除OSS文件时需要指定包含文件后缀在内的完整路径，例如abc/efg/123.jpg。
        DeleteObjectsResult deleteObjectsResult = ossClient.deleteObjects(new DeleteObjectsRequest(bucketName).withKeys(objectIDList));
        List<String> deletedObjects = deleteObjectsResult.getDeletedObjects();
        // 关闭OSSClient。
        ossClient.shutdown();
    }

    public AliOssClient(RedisUtils redisUtils) {
        this.redisUtils = redisUtils;
    }
}
